home *** CD-ROM | disk | FTP | other *** search
- /* Parse command line, set up command arguments Unix-style, and call function.
- * Note: argument is modified (delimiters are overwritten with nulls)
- *
- * Copyright 1991 Phil Karn, KA9Q
- *
- * Improved error handling by Brian Boesch of Stanford University
- * Feb '91 - Bill Simpson
- * bit16cmd for PPP
- * Mar '91 - Glenn McGregor
- * handle string escaped sequences
- */
- #ifdef MSDOS
- #include <conio.h>
- #endif
- #include "global.h"
- #include "ctype.h"
- #include "proc.h"
- #include "commands.h"
- #include "session.h"
- #include "pktdrvr.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: cmdparse.c,v 1.15 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- #ifdef LOCK
- int Kblocked;
- char *Kbpasswd;
- #endif
-
- extern long btol (char *s);
-
- int cmdparse_newproc_type = PTYPE_NORMAL;
-
- static void redir_cleanup (void);
-
-
- struct boolcmd {
- const char *str; /* Token */
- int val; /* Value */
- };
-
-
- static struct boolcmd Boolcmds[] =
- {
- {"y", 1}, /* Synonyms for "true" */
- {"yes", 1},
- {"true", 1},
- {"on", 1},
- {"1", 1},
- {"set", 1},
- {"enable", 1},
-
- {"n", 0}, /* Synonyms for "false" */
- {"no", 0},
- {"false", 0},
- {"off", 0},
- {"0", 0},
- {"clear", 0},
- {"disable", 0},
- {NULLCHAR, 0}
- };
-
- static char *stringparse (char *line, int braced);
-
-
- static char *
- stringparse (line, braced)
- char *line;
- int braced;
- {
- register char *cp = line;
- unsigned long num;
- char check = (braced) ? '}' : '\"';
-
- while (*line != '\0' && *line != check) {
- if (*line == '\\') {
- line++;
- switch (*line++) {
- case 'n': *cp++ = '\n';
- break;
- case 't': *cp++ = '\t';
- break;
- case 'v': *cp++ = '\v';
- break;
- case 'b': *cp++ = '\b';
- break;
- case 'r': *cp++ = '\r';
- break;
- case 'f': *cp++ = '\f';
- break;
- #ifdef TNOS_68K
- case 'l': *cp++ = '\l';
- break;
- #endif
- case 'a': *cp++ = '\007';
- break;
- case '\\': *cp++ = '\\';
- break;
- case '\?': *cp++ = '\?';
- break;
- case '\'': *cp++ = '\'';
- break;
- case ';': *cp++ = ';';
- break;
- case '{': *cp++ = '{';
- break;
- case '}': *cp++ = '}';
- break;
- case '>': *cp++ = '>';
- break;
- case '\"': *cp++ = '\"';
- break;
- case 'x': num = strtoul (--line, &line, 16);
- *cp++ = (char) num;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': num = strtoul (--line, &line, 8);
- *cp++ = (char) num;
- break;
- case '\0': return NULLCHAR;
- default: *cp++ = *(line - 1);
- break;
- }
- } else
- *cp++ = *line++;
- }
-
- if (*line == check)
- line++; /* skip final quote */
- *cp = '\0'; /* terminate string */
- return line;
- }
-
-
-
- static void
- redir_cleanup (void)
- {
- if (Curproc == Command->proc && Command->rfile != NULLCHAR) {
- rflush ();
- kwait (NULL);
- Command->rfile = NULLCHAR;
- fputc ('\n', Command->record);
- (void) fclose (Command->record);
- Command->record = NULLFILE;
- }
- }
-
-
-
- int
- cmdparse (cmds, line, p)
- struct cmds cmds[];
- register char *line;
- void *p;
- {
- struct cmds *cmdp;
- char const *argv[NARG];
- char *cp, c;
- char **pargv;
- int argc, i, isconv;
- char *nextline;
- int inbrace, indquote, done;
-
- int check4redir = 0;
- char *doredir;
- int inAcommentline;
-
- /* Remove cr/lf */
- rip (line);
-
- if (Curproc == Command->proc)
- check4redir = 1;
-
- loop: /* this section handles multi-command lines, using a ';' */
- redir_cleanup ();
- nextline = NULLCHAR;
- doredir = NULLCHAR;
- inAcommentline = 0;
- line = skipwhite (line);
- done = inbrace = indquote = 0;
- for (cp = line; *cp && !done; cp++) {
- switch (*cp) {
- case '#': if (cp == line)
- inAcommentline = 1;
- break;
- case '{': if (!indquote && !inAcommentline)
- inbrace += 1;
- break;
- case '}': if (!indquote && !inAcommentline)
- inbrace -= 1;
- break;
- case '\"': if (!inbrace && !inAcommentline)
- indquote ^= 1;
- break;
- case '\\': if (!inAcommentline) {
- c = *(cp + 1);
- if (c == '{' || c == '}' || c == '\"' || c == ';' || (check4redir && c == '>'))
- cp++;
- }
- break;
- case ';': if (!inbrace && !indquote && !inAcommentline) {
- *cp++ = 0;
- nextline = cp;
- done = 1;
- }
- break;
- case '>': if (check4redir && !inAcommentline) {
- *cp++ = 0;
- doredir = cp;
- }
- break;
- default: break;
- }
- }
-
- for (argc = 0; argc < NARG; argc++)
- argv[argc] = NULLCHAR;
-
- if (check4redir && doredir != NULLCHAR) {
- /* output redirection found */
- Command->rfile = skipwhite (doredir);
- Command->record = fopen (Command->rfile, APPEND_TEXT);
- if (Command->record == NULLFILE) {
- tprintf ("Can't open %s: %s\n", Command->rfile, SYS_ERRLIST(errno));
- Command->rfile = NULLCHAR;
- }
- }
- for (argc = 0; argc < NARG;) {
- register int qflag = FALSE;
- register int qflag2 = FALSE;
-
- /* Skip leading white space */
- while (*line == ' ' || *line == '\t')
- line++;
- if (*line == '\0')
- break;
- /* return if comment character first non-white */
- if (argc == 0 && *line == '#')
- goto multichk;
- /* Check for quoted token */
- if (*line == '"' && strchr (line + 1, '"')) {
- line++; /* Suppress quote */
- qflag = TRUE;
- } else if (*line == '{' && strchr (line + 1, '}')) { /* Check for braced token */
- line++; /* Suppress quote */
- qflag2 = TRUE;
- }
- argv[argc++] = line; /* Beginning of token */
-
- if (qflag || qflag2) { /* Find terminating delimiter */
- if ((line = stringparse (line, qflag2)) == NULLCHAR)
- goto errret;
- } else {
- /* Find space or tab. If not present,
- * then we've already found the last
- * token.
- */
- if ((cp = strpbrk (line, " \t")) == NULLCHAR)
- break;
- *cp++ = '\0';
- line = cp;
- }
- }
- if (argc < 1) { /* empty command line */
- argc = 1;
- argv[0] = "";
- }
- #ifdef LOCK
- /* Check to see if this is the Command session.
- * If so, check to see if the keyboard is locked
- * Added 12/12/91 WG7J
- * Also, skips this check if it is a command from the AT queue 12/16/93 KO4KS
- */
- if ((Curproc->input == Command->input) && strcmp ("AT handler", Curproc->name))
- if (Kblocked) { /*check argv[0] for password!*/
- if (stricmp (argv[0], Kbpasswd)) {
- tputs ("\nKeyboard remains locked\n");
- return 0;
- }
- Command->ttystate.echo = 1; /* turn character echo back on ! */
- Kblocked = 0; /* correct password, so unlock */
- tputc ('\n');
- redir_cleanup ();
- return 0;
- }
- #endif
-
- /* Look up command in table; prefix matches are OK */
- for (cmdp = cmds; cmdp->name != NULLCHAR; cmdp++) {
- if (strncmpi (argv[0], cmdp->name, strlen (argv[0])) == 0)
- break;
- }
- if (cmdp->name == NULLCHAR) {
- #ifdef SCRIPTING
- if (Curproc->gotolabel)
- goto multichk;
- #endif
- if (cmdp->argc_errmsg != NULLCHAR)
- tprintf ("%s\n", cmdp->argc_errmsg);
- goto errret;
- } else {
- #ifdef SCRIPTING
- /* if we are in a goto command, and this is NOT a label
- command, skip it.... */
- if (Curproc->gotolabel && strcmp ("label", cmdp->name))
- goto multichk;
- #endif
- if (argc < cmdp->argcmin) {
- /* Insufficient arguments */
- tprintf ("Usage: %s\n", (cmdp->argc_errmsg) ? cmdp->argc_errmsg : "Try a '?' parameter for help");
- goto errret;
- } else {
- if (cmdp->stksize == 0) {
- i = (*cmdp->func) (argc, (char **) argv, p);
- if (i)
- return i;
- goto multichk;
- } else {
- /* Make private copy of argv and args,
- * spawn off subprocess and return.
- */
- isconv = (!stricmp (cmdp->name, "conference")
- || !stricmp (cmdp->name, "rlogin")
- || !stricmp (cmdp->name, "quote")
- || !stricmp (cmdp->name, "tutor")
- || !stricmp (cmdp->name, "info")
- || !stricmp (cmdp->name, "news"));
- pargv = (char **) callocw ((unsigned) ((isconv) ? 3 : argc), sizeof (char *));
-
- for (i = 0; i < argc; i++)
- pargv[i] = strdup (argv[i]);
- (void) newproc (cmdp->name, (unsigned) cmdp->stksize,
- (void (*)(int, void *, void *)) cmdp->func, (isconv) ? 3 : argc, pargv, p, 1);
- goto multichk;
- }
- }
- }
-
- multichk:
- if (nextline != NULLCHAR) {
- line = nextline;
- goto loop;
- }
- redir_cleanup ();
- return 0;
-
-
- errret:
- if (nextline != NULLCHAR)
- tprintf ("*** Didn't execute: %s\n", nextline);
- redir_cleanup ();
- return -1;
- }
-
-
- /* Call a subcommand based on the first token in an already-parsed line */
- int
- subcmd (tab, argc, argv, p)
- struct cmds tab[];
- int argc;
- char *argv[];
- void *p;
- {
- register struct cmds *cmdp;
- struct proc *pp;
- char **pargv;
- int found = 0;
- int i;
-
- /* Strip off first token and pass rest of line to subcommand */
- if (argc < 2) {
- if (argc < 1)
- tputs ("SUBCMD - Don't know what to do?\n");
- else
- #if 1
- dohelper ("valid subcommands:\n", tab, NULLCHAR, NULLCHAR, NULLCHAR);
- #else
- tprintf ("\"%s\" - takes at least one argument\n", argv[0]);
- #endif
- return -1;
- }
- argc--;
- argv++; /*lint !e608 */
- for (cmdp = tab; cmdp->name != NULLCHAR; cmdp++) {
- if (strncmpi (argv[0], cmdp->name, strlen (argv[0])) == 0) {
- found = 1;
- break;
- }
- }
- if (!found) {
- dohelper ("valid subcommands:\n", tab, NULLCHAR, NULLCHAR, NULLCHAR);
- return -1;
- }
- if (argc < cmdp->argcmin) {
- if (cmdp->argc_errmsg != NULLCHAR)
- tprintf ("Usage: %s\n", cmdp->argc_errmsg);
- return -1;
- }
- if (cmdp->stksize == 0)
- return (*cmdp->func) (argc, argv, p);
- else {
- /* Make private copy of argv and args */
- pargv = (char **) callocw ((unsigned) argc, sizeof (char *));
-
- for (i = 0; i < argc; i++)
- pargv[i] = strdup (argv[i]);
- pp = newproc (cmdp->name, (unsigned) cmdp->stksize,
- (void (*)(int, void *, void *)) cmdp->func, argc, pargv, p, 1);
- pp->ptype = cmdparse_newproc_type;
- return (0);
- }
- }
-
-
- /* Subroutine for setting and displaying boolean flags */
- int
- setbool (var, label, argc, argv)
- int *var;
- char const *label;
- int argc;
- char *argv[];
- {
- struct boolcmd *bc;
-
- if (argc < 2) {
- tprintf ("%s: %s\n", label, *var ? "on" : "off");
- return 1;
- }
- for (bc = Boolcmds; bc->str != NULLCHAR; bc++) {
- if (strcmpi (argv[1], bc->str) == 0) {
- *var = bc->val;
- return 0;
- }
- }
- tputs ("Valid options:");
- for (bc = Boolcmds; bc->str != NULLCHAR; bc++)
- if (tprintf (" %s", bc->str) == EOF)
- return 1;
- tputc ('\n');
- return 1;
- }
-
-
- /* Subroutine for setting and displaying bit values */
- int
- bit16cmd (int16 *bits, int16 mask, const char *label, int argc, char *argv[])
- {
- int doing = (*bits & mask);
- int result = setbool (&doing, label, argc, argv);
-
- if (!result) {
- if (doing)
- *bits |= mask;
- else
- *bits &= ~mask;
- }
- return result;
- }
-
-
- /* Subroutine for setting and displaying long variables */
- int
- setlong (var, label, argc, argv)
- long *var;
- char const *label;
- int argc;
- char *argv[];
- {
- if (argc < 2) {
- tprintf ("%s: %ld (0x%08lx)\n", label, *var, *var);
- return 1;
- } else {
- if (!strncmp (argv[1], "0x", 2))
- *var = htol (argv[1]);
- else if (argv[1][0] == '%')
- *var = btol (argv[1]);
- else
- *var = atol (argv[1]);
- return 0;
- }
-
- }
-
-
- /* Subroutine for setting and displaying short variables */
- int
- setshort (var, label, argc, argv)
- unsigned short *var;
- char const *label;
- int argc;
- char *argv[];
- {
- if (argc < 2) {
- tprintf ("%s: %u (0x%04x)\n", label, *var, *var);
- return 1;
- } else {
- if (!strncmp (argv[1], "0x", 2))
- *var = (int16) htoi (argv[1]);
- else if (argv[1][0] == '%')
- *var = (unsigned short) btol (argv[1]);
- else
- *var = (int16) atoi (argv[1]);
- return 0;
- }
- }
-
-
- /* Subroutine for setting and displaying integer variables */
- int
- setint (var, label, argc, argv)
- int *var;
- char const *label;
- int argc;
- char *argv[];
- {
- if (argc < 2) {
- tprintf ("%s: %i (0x%04x)\n", label, *var, *var);
- return 1;
- } else {
- if (!strncmp (argv[1], "0x", 2))
- *var = htoi (argv[1]);
- else if (argv[1][0] == '%')
- *var = (int) btol (argv[1]);
- else
- *var = atoi (argv[1]);
- return 0;
- }
-
- }
-
-
- /* Subroutine for setting and displaying unsigned integer variables */
- int
- setuns (var, label, argc, argv)
- unsigned *var;
- char const *label;
- int argc;
- char *argv[];
- {
- if (argc < 2) {
- tprintf ("%s: %u (0x%04x)\n", label, *var, *var);
- return 1;
- } else {
- if (!strncmp (argv[1], "0x", 2))
- *var = (int16) htoi (argv[1]);
- else if (argv[1][0] == '%')
- *var = (unsigned) btol (argv[1]);
- else
- *var = (int16) atoi (argv[1]);
- return 0;
- }
- }
-
-
- /* Subroutine for setting and displaying int variables (with range check) */
- int
- setintrc (int16 *var, char const *label, int argc, char *argv[], int minval, int16 maxval)
- {
- int tmp;
-
- if (argc < 2)
- tprintf ("%s: %u (0x%04x)\n", label, *var, *var);
- else {
- if (!strncmp (argv[1], "0x", 2))
- tmp = htoi (argv[1]);
- else if (argv[1][0] == '%')
- tmp = (int) btol (argv[1]);
- else
- tmp = atoi (argv[1]);
- if (isalpha (*argv[1]) || tmp < minval || tmp > maxval) {
- tprintf ("%s must be %i..%i\n", label, minval, maxval);
- return 1;
- }
- *var = (int16) tmp;
- }
- return 0;
- }
-